package com.doudou.collection.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.doudou.collection.mapper.UserMapper;
import com.doudou.collection.pojo.dto.*;
import com.doudou.collection.pojo.entity.User;
import com.doudou.collection.pojo.entity.UserDetail;
import com.doudou.collection.pojo.vo.UserVO;
import com.doudou.collection.response.ResultVO;
import com.doudou.collection.response.StatusCode;
import com.doudou.collection.security.CustomUserDetails;
import com.doudou.collection.service.UserService;
import com.doudou.collection.utils.RedisConstants;
import com.doudou.collection.utils.RegexUtils;
import com.doudou.collection.utils.SnowflakeIdGenerator;
import com.doudou.collection.utils.UsernameGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName UserServiceImpl<br>
 * @Description 用户业务逻辑类实现类<br>
 * @Author 李浩文<br>
 * @Date 2023/6/2 17:43<br>
 * @Version 1.0<br>
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AuthenticationManager manager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public ResultVO addNewByUsername(String username, String password) {
        log.debug("正在处理用户注册业务功能: 账号-->{} 密码-->{}", username, password);

        //判断用户名格式是否正确
        if (RegexUtils.isUsernameInvalid(username)) {
            log.error("该用户名格式错误！ ===> {}", username);
            return new ResultVO(StatusCode.USERNAME_FORMAT_ERROR);
        }

        //判断密码格式是否正确
        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        //查询用户是否存在
        UserVO userVO = userMapper.queryByUsername(username);
        if (userVO != null) {
            log.error("用户已存在！");
            return new ResultVO(StatusCode.USERNAME_ALREADY_EXISTS);
        }

        //插入用户信息
        User user = new User();
        user.setId(SnowflakeIdGenerator.generateUniqueId());
        user.setUsername(username);
        user.setIcon("/douIcon.png");
        user.setCreateTime(new Date());
        user.setPassword(passwordEncoder.encode(password));
        userMapper.insertUser(user);

        //插入用户详情信息
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        userMapper.insertUserDetail(userDetail);

        return ResultVO.ok();
    }

    @Override
    public ResultVO addNewByEmail(String email, String password) {
        log.debug("正在处理邮箱注册业务功能: 邮箱-->{} 密码-->{}", email, password);

        //邮箱格式是否正确
        if (RegexUtils.isEmailInvalid(email)) {
            log.error("邮箱格式错误！");
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        //判断密码格式是否正确
        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        //查询用户是否存在
        UserVO userVO = userMapper.queryByEmail(email);
        if (userVO != null) {
            log.error("邮箱已存在！");
            return new ResultVO(StatusCode.EMAIL_ALREADY_EXISTS);
        }

        //插入用户信息
        User user = new User();
        //自动生成账户的用户名
        user.setUsername(UsernameGenerator.generateUsername("DDJ"));
        //通过雪花算法生成唯一id
        user.setId(SnowflakeIdGenerator.generateUniqueId());
        user.setIcon("/douIcon.png");
        user.setCreateTime(new Date());
        user.setPassword(passwordEncoder.encode(password));
        userMapper.insertUser(user);

        //插入用户详情信息
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        userDetail.setEmail(email);
        userMapper.insertUserDetail(userDetail);

        return ResultVO.ok();
    }

    @Override
    public ResultVO addNewByPhone(String phone, String password) {
        log.debug("正在处理手机注册业务功能: 手机-->{} 密码-->{}", phone, password);

        //手机号码格式是否正确
        if (RegexUtils.isPhoneInvalid(phone)) {
            log.error("手机号码格式错误！");
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        //判断密码格式是否正确
        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        //查询用户是否存在
        UserVO userVO = userMapper.queryByPhone(phone);
        if (userVO != null) {
            log.error("手机号已存在！");
            return new ResultVO(StatusCode.PHONE_ALREADY_EXISTS);
        }

        //插入用户信息
        User user = new User();
        //自动生成账户的用户名
        user.setUsername(UsernameGenerator.generateUsername("DDJ"));
        user.setIcon("/douIcon.png");
        user.setId(SnowflakeIdGenerator.generateUniqueId());
        user.setCreateTime(new Date());
        user.setPassword(passwordEncoder.encode(password));
        userMapper.insertUser(user);

        //插入用户详情信息
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        userDetail.setPhone(phone);
        userMapper.insertUserDetail(userDetail);

        return ResultVO.ok();
    }

    @Override
    public ResultVO addNewByPhoneAndCode(String phone, String code) {
        log.debug("正在处理手机验证码注册业务功能: 手机-->{} 验证码-->{}", phone, code);

        //手机号码格式是否正确
        if (RegexUtils.isPhoneInvalid(phone)) {
            log.error("手机号码格式错误！");
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        //判断验证码格式是否正确
        if (RegexUtils.isUsernameInvalid(code)) {
            log.error("该验证码格式错误！ ===> {}", code);
            return new ResultVO(StatusCode.CODE_FORMAT_ERROR);
        }

        //判断验证码是否正确
        String phoneCode = redisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + phone);
        if (!code.equals(phoneCode)) {
            log.error("手机验证码错误!");
            return new ResultVO(StatusCode.CODE_ERROR);
        }

        //查询用户是否存在
        UserVO userVO = userMapper.queryByPhone(phone);
        if (userVO != null) {
            log.error("手机号已存在！");
            return new ResultVO(StatusCode.PHONE_ALREADY_EXISTS);
        }

        //插入用户信息
        User user = new User();
        //自动生成账户的用户名
        user.setUsername(UsernameGenerator.generateUsername("DDJ"));
        user.setId(SnowflakeIdGenerator.generateUniqueId());
        user.setIcon("/douIcon.png");
        user.setCreateTime(new Date());
        userMapper.insertUser(user);

        //插入用户详情信息
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        userDetail.setPhone(phone);
        userMapper.insertUserDetail(userDetail);

        return ResultVO.ok();
    }

    @Override
    public ResultVO addNewByEmailAndCode(String email, String code) {
        log.debug("正在处理手机验证码注册业务功能: 邮箱-->{} 验证码-->{}", email, code);

        //邮箱格式是否正确
        if (RegexUtils.isEmailInvalid(email)) {
            log.error("邮箱格式错误！");
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        //判断验证码格式是否正确
        if (RegexUtils.isUsernameInvalid(code)) {
            log.error("该验证码格式错误！ ===> {}", code);
            return new ResultVO(StatusCode.CODE_FORMAT_ERROR);
        }

        //判断验证码是否正确
        String emailCode = redisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + email);
        if (!code.equals(emailCode)) {
            log.error("邮箱验证码错误!");
            return new ResultVO(StatusCode.CODE_ERROR);
        }

        //查询用户是否存在
        UserVO userVO = userMapper.queryByEmail(email);
        if (userVO != null) {
            log.error("邮箱已存在！");
            return new ResultVO(StatusCode.EMAIL_ALREADY_EXISTS);
        }

        //插入用户信息
        User user = new User();
        //自动生成账户的用户名
        user.setUsername(UsernameGenerator.generateUsername("DDJ"));
        user.setIcon("/douIcon.png");
        user.setId(SnowflakeIdGenerator.generateUniqueId());
        user.setCreateTime(new Date());
        userMapper.insertUser(user);

        //插入用户详情信息
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        userDetail.setEmail(email);
        userMapper.insertUserDetail(userDetail);

        return ResultVO.ok();
    }

    @Override
    public ResultVO loginByUsername(String username, String password) {
        log.debug("正在处理用户名登录业务功能: {} {}", username, password);

        if (RegexUtils.isUsernameInvalid(username)) {
            log.error("该用户名格式错误！ ===> {}", username);
            return new ResultVO(StatusCode.USERNAME_FORMAT_ERROR);
        }

        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        Authentication result = authentication(username, password);

        return new ResultVO(StatusCode.LOGIN_SUCCESS, result.getPrincipal());
    }

    @Override
    public ResultVO loginByEmail(String email, String password) {
        log.debug("正在处理邮箱登录业务功能: {} {}", email, password);

        if (RegexUtils.isEmailInvalid(email)) {
            log.error("该邮箱格式错误！ ===> {}", email);
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        Authentication result = authentication(email, password);

        return new ResultVO(StatusCode.LOGIN_SUCCESS, result.getPrincipal());
    }

    @Override
    public ResultVO loginByPhone(String phone, String password) {
        log.debug("正在处理手机号登录业务功能: {} {}", phone, password);

        if (RegexUtils.isPhoneInvalid(phone)) {
            log.error("该手机号格式错误！ ===> {}", phone);
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        if (RegexUtils.isPasswordInvalid(password)) {
            log.error("该密码格式错误！ ===> {}", password);
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        Authentication result = authentication(phone, password);


        return new ResultVO(StatusCode.LOGIN_SUCCESS, result.getPrincipal());
    }

    @Override
    public ResultVO loginByPhoneAndCode(String phone, String code) {
        log.debug("正在处理手机号登录业务功能: {} {}", phone, code);

        if (RegexUtils.isPhoneInvalid(phone)) {
            log.error("该手机号格式错误！ ===> {}", phone);
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        if (RegexUtils.isCodeInvalid(code)) {
            log.error("该验证码格式错误！ ===> {}", code);
            return new ResultVO(StatusCode.CODE_FORMAT_ERROR);
        }

        UserVO userVO = userMapper.queryByPhone(phone);
        if (userVO == null) {
            //根据手机号码没有查询到指定用户
            return new ResultVO(StatusCode.PHONE_ERROR);
        }
        if (!code.equals(redisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + phone))) {
            //验证码错误 验证失败
            return new ResultVO(StatusCode.CODE_ERROR);
        }

        Authentication result = authentication(userVO);

        return new ResultVO(StatusCode.LOGIN_SUCCESS, result.getPrincipal());
    }

    @Override
    public ResultVO loginByEmailAndCode(String email, String code) {
        log.debug("正在处理手机号登录业务功能: {} {}", email, code);

        if (RegexUtils.isEmailInvalid(email)) {
            log.error("该邮箱格式错误！ ===> {}", email);
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        if (RegexUtils.isCodeInvalid(code)) {
            log.error("该验证码格式错误！ ===> {}", code);
            return new ResultVO(StatusCode.CODE_FORMAT_ERROR);
        }

        UserVO userVO = userMapper.queryByEmail(email);
        if (userVO == null) {
            //根据邮箱没有查询到指定用户
            return new ResultVO(StatusCode.EMAIL_ERROR);
        }
        String redisEmailCode = redisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + email);
        if (!code.equals(redisEmailCode)) {
            //验证码错误 验证失败
            return new ResultVO(StatusCode.CODE_ERROR);
        }

        Authentication result = authentication(userVO);

        return new ResultVO(StatusCode.LOGIN_SUCCESS, result.getPrincipal());
    }

    private Authentication authentication(UserVO userVO) {
        CustomUserDetails details = new CustomUserDetails(userVO, AuthorityUtils.createAuthorityList("ADMIN"));
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(details, null);
        token.setDetails(details);
        SecurityContextHolder.getContext().setAuthentication(token);
        return token;
    }

    private Authentication authentication(String username, String password) {
        Authentication result = manager.authenticate(
                new UsernamePasswordAuthenticationToken(username, password)
        );
        SecurityContextHolder.getContext().setAuthentication(result);
        return result;
    }

    @Override
    public void updateUserDetailById(UserDetailDTO userDetailDTO) {
        log.debug("正在处理用户修改个人信息的业务逻辑");

        userMapper.updateUserDetailById(userDetailDTO);
        userMapper.updateTimeById(userDetailDTO.getId(), new Date());//记录修改时间
    }

    @Override
    public ResultVO sendCodeToPhone(String phone) {
        log.debug("正在处理发送手机验证码的业务功能");

        //1.检验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2.不符合返回错误信息
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        //3.符合生成验证码
        String code = RandomUtil.randomNumbers(6);

        //4.保存到redis
        redisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + phone, code,
                RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);

        //5.发送验证码(模拟)
        log.info("验证码 ---> {}", code);

        //返回ok
        return ResultVO.ok();
    }

    @Override
    public ResultVO sendCodeToEmail(String email) {
        log.debug("正在处理发送邮箱验证码的业务功能");

        //1.检验手机号
        if (RegexUtils.isEmailInvalid(email)) {
            //2.不符合返回错误信息
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        //3.符合生成验证码
        String code = RandomUtil.randomNumbers(6);

        //4.保存到redis
        redisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + email, code,
                RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);

        //5.发送验证码(模拟)
        log.info("验证码 ---> {}", code);

        //返回ok
        return ResultVO.ok();
    }

    @Override
    public ResultVO updateUsernameById(UserUpdateNameDTO userUpdateNameDTO) {
        log.debug("正在处理修改用户名的业务逻辑");

        if (RegexUtils.isUsernameInvalid(userUpdateNameDTO.getUsername())) {
            log.error("该用户名格式错误！ ===> {}", userUpdateNameDTO.getUsername());
            return new ResultVO(StatusCode.USERNAME_FORMAT_ERROR);
        }

        UserVO userVO = userMapper.queryByUsername(userUpdateNameDTO.getUsername());
        if (userVO != null) {
            log.error("用户名一致,不需要修改！");
            return new ResultVO(StatusCode.SAME_USERNAME);
        }

        userMapper.updateUsernameById(userUpdateNameDTO);
        userMapper.updateTimeById(userUpdateNameDTO.getId(), new Date());
        return ResultVO.ok();
    }

    @Override
    public ResultVO updatePasswordById(UserUpdatePwdDTO userUpdatePwdDTO) {
        log.debug("正在处理修改密码的业务逻辑");

        if (RegexUtils.isPasswordInvalid(userUpdatePwdDTO.getPassword())) {
            log.error("该密码格式错误！ ===> {}", userUpdatePwdDTO.getPassword());
            return new ResultVO(StatusCode.PASSWORD_FORMAT_ERROR);
        }

        String oldPassword = userMapper.queryPasswordById(userUpdatePwdDTO.getId());
        if (userUpdatePwdDTO.getPassword().equals(oldPassword)) {
            log.warn("密码一致,不需要修改！");
            return new ResultVO(StatusCode.SAME_PASSWORD);
        }

        userMapper.updatePasswordById(userUpdatePwdDTO);
        userMapper.updateTimeById(userUpdatePwdDTO.getId(), new Date());
        return ResultVO.ok();
    }

    @Override
    public ResultVO updateEmailById(UserUpdateEmailDTO userUpdateEmailDTO) {
        log.debug("正在处理修改邮箱的业务逻辑");

        if (RegexUtils.isEmailInvalid(userUpdateEmailDTO.getEmail())) {
            log.error("该邮箱格式错误！ ===> {}", userUpdateEmailDTO.getEmail());
            return new ResultVO(StatusCode.EMAIL_FORMAT_ERROR);
        }

        UserVO userVO = userMapper.queryByEmail(userUpdateEmailDTO.getEmail());
        if (userVO != null) {
            log.warn("邮箱一致,不需要修改！");
            return new ResultVO(StatusCode.SAME_EMAIL);
        }

        userMapper.updateEmailById(userUpdateEmailDTO);
        userMapper.updateTimeById(userUpdateEmailDTO.getId(), new Date());
        return ResultVO.ok();
    }

    @Override
    public ResultVO updatePhoneById(UserUpdatePhoneDTO userUpdatePhoneDTO) {
        log.debug("正在处理修改手机号的业务逻辑");

        if (RegexUtils.isPhoneInvalid(userUpdatePhoneDTO.getPhone())) {
            log.error("该手机号格式错误！ ===> {}", userUpdatePhoneDTO.getPhone());
            return new ResultVO(StatusCode.PHONE_FORMAT_ERROR);
        }

        UserVO userVO = userMapper.queryByPhone(userUpdatePhoneDTO.getPhone());
        if (userVO != null) {
            log.warn("手机号一致,不需要修改！");
            return new ResultVO(StatusCode.SAME_PASSWORD);
        }

        userMapper.updatePhoneById(userUpdatePhoneDTO);
        userMapper.updateTimeById(userUpdatePhoneDTO.getId(), new Date());
        return ResultVO.ok();
    }
}









